const zbRouter = function () {
    "use strict";
    this.domain = location.origin + '/';
    this.urlPath = location.pathname.substring(1);
    this.Router = [];
    this.defaultRouter = 'index';
    this.splitChar1 = ',';
    this.splitChar2 = ':';
    this.catchChar = '@'; //正则表达式捕获的值,存放在以此字符开头的变量中
    this.hookBefore = null; //全局hook, 路由前执行
    this.publicParmas = {};

    //初始化
    this.init = function (routers, routerName=null) {
        this.Router = routers;

        let that = this;
        window.onpopstate = function(event) {
            let curUlrPath = location.pathname.substring(1);
            if (curUlrPath !== that.urlPath) {
                that.route(curUlrPath);
            }
            return false;
        }

        if (routerName === null || routerName.length === 0) {
            if (!location.pathname || location.pathname.length === 0) {
                this.route(this.defaultRouter);
            } else {
                this.route(this.urlPath);
            }
        }
    };

    //执行路由
    this.route = function (str = null, replace='0') {

        str = (str === null || str.length === 0) ? this.defaultRouter : str;

        let info = this.parseRouter(str);

        if (info === false) {
            this.error('未匹配到路由信息: ' + str + '; 使用默认路由');
            info = this.parseRouter(this.defaultRouter);
            replace = '1';
            str = this.defaultRouter;
        }

        //执行全局hook
        if (this.hookBefore && (typeof this.hookBefore === 'function')) {
            this.hookBefore(info['args']);
        }

        let curUrl = this.buildUrl(str);
        if (str === document.location.pathname.substring(1)) {
            replace = '1';
        }

        if (replace === '0') {
            history.pushState(null, "", curUrl);
            this.urlPath = str;
        } else if (replace === '1') {
            history.replaceState(null, "", curUrl);
            this.urlPath = str;
        }

        //替换模板
        if (info['args']['tpl']) {
            let tplId = info['args']['tpl'];
            let target = '';
            if (info['args']['target'] !== undefined) {
                target = info['args']['target'];
            } else {
                target = tplId.substring(3); //默认模板id前是字符串tpl
            }

            info['args']['target'] = target;

            document.getElementById(target).innerHTML = document.getElementById(tplId).innerHTML;
        }

        //调用路由前hook
        if (info['hookBefore'] && (typeof info['hookBefore'] === 'function')) {
            info['hookBefore'](info['args']);
        }
        //调用路由中的函数
        if (info['callback'] && (typeof info['callback'] === 'function')) {
            info['callback'](info['args']);
        }

    };

    //更改浏览器地址栏URL，并追加入history
    this.pushUrl = function (uri) {
        let url = this.buildUrl(uri);
        history.pushState(null, "", url);
        this.urlPath = url;
    }

    //更改浏览器地址栏URL，并替换history当前地址
    this.replaceUrl = function (uri) {
        let url = this.buildUrl(uri);
        history.replaceState(null, "", url);
        this.urlPath = url;
    }

    //解析字符串看是否匹配到路由, 匹配到就返回路由信息, 未匹配到就返回false
    this.parseRouter = function (str) {
        for (let i=0; i< this.Router.length; i++) {
            let routerInfo = this.Router[i];
            let pattern = routerInfo['pattern'];
            let params = routerInfo['params'];
            let isMatch = false;

            if (pattern === str) {
                isMatch = true;
            } else {
                let reg = new RegExp('^' + pattern + '$');
                let rs = reg.exec(str);

                //匹配的值的数量 == @的个数
                if (rs !== null && params.split(this.catchChar).length === rs.length) {
                    isMatch = true;
                    for (let j = 1; j < rs.length; j++) {
                        params = params.replace(this.catchChar + j, rs[j]);
                    }
                }
            }

            if (isMatch) {
                routerInfo['args'] = this.explodeArgs(params, this.splitChar1, this.splitChar2);
                return routerInfo;
            }
        }

        //return str;
        return false;
    };

    //请求接口
    this.request = function (src, params = {}, callback = null, async=false) {
        let form = new FormData(); // FormData 对象
        let xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
        xhr.open("post", src, async); //post方式，url为服务器请求地址，true 该参数规定请求是否异步处理。
        xhr.onload = function (evt) {
            if (callback && xhr.response) {
                callback(JSON.parse(xhr.response)); //默认返回内容为json
            } else {
                console.log(xhr.response)
            }
        }

        xhr.onerror =  function(evt) {
            console.log(xhr.response);
        }; //请求失败
        xhr.ontimeout =  function(evt) {
            console.log('请求超时！' + src);
        }; //请求超时

        //form.append(this.fileInputId, this.blobImage, "image_"+Date.parse(new Date())+".jpg"); // 文件对象
        for (let i in params) {
            form.append(i, params[i]);
        }
        xhr.send(form); //开始上传，发送form数据
    }

    //将字符串拆分成键值对
    this.explodeArgs = function (str, char1, char2) {
        let arr = str.split(char1);
        let list = {};
        for (let i = 0; i < arr.length; i++) {
            let tmp = arr[i].split(char2);
            list[tmp[0]] = tmp[1];
        }

        return list;
    }

    //公共error处理方法
    this.error = function (str) {
        console.log(str);
    }

    //解析查询参数成对象
    this.parseQuery = function (query='') {
        if (query.length === 0) {
            query = window.location.href;
        }
        let pos = query.indexOf('?');
        if (pos === -1) {
            return {};
        }

        query = query.substring(pos + 1);
        query = decodeURIComponent(query);

        if (query.length === 0) {
            return {};
        }

        let items = null, item = null, name = null, value = null;

        if (query.indexOf('&') === -1) {
            items = query.split("=");
            name = items[0];
            value = items[1];
            let tmp = {};
            tmp[name] = value;
            return tmp;
        }

        let args = {};
        items = query.split("&");
        for(let i=0; i < items.length; i++){
            item = items[i].split("=");
            if(item[0]){
                name = item[0];
                value = item[1] ? item[1] : "";
                args[name] = value;
            }
        }

        return args;
    };

    //组装url
    this.buildUrl = function (path, obj=null) {
        let url = location.protocol + '//' + location.host +'/' + path;

        if (obj!==null && obj.length !== undefined && obj.length > 0) {
            let arr = [];
            for (let j in obj) {
                if (obj.hasOwnProperty(j)) {
                    arr.push(j + '=' + param[j]);
                }
            }
            url = url + '?' + arr.join('&');
        }

        return url;
    };

    //替换dom内层html内容
    this.repeatInnerHTML = function (selector, arr, func=null) {
        let tplDom = document.querySelector(selector);
        if (!tplDom) {
            this.error('未找到: '+selector);
            return;
        }

        tplDom.innerHTML = this.repeatString(tplDom.innerHTML, arr, func);
    }

    //替换dom
    this.repeatOuterHTML = function (selector, arr, func=null) {
        let tplDom = document.querySelector(selector);
        if (!tplDom) {
            this.error('未找到: '+selector);
            return;
        }

        tplDom.outerHTML = this.repeatString(tplDom.outerHTML, arr, func);
    };

    //用数组重复渲染字符串
    this.repeatString = function (tplDom, arr, func=null) {
        if (tplDom.length === 0) {
            this.error('字符串长度为空');
            return;
        }

        if (arr.length === 0) {
            this.error('数据为空');
            return tplDom;
        }

        let tpl = tplDom;
        let out = '';
        for (let i=0; i<arr.length; i++) {
            if (typeof func === 'function') {
                arr[i] = func(arr[i]);
            }
            let map = arr[i];
            let tmp = tpl;
            for (let j in map) {
                let re = new RegExp('{' + j + '}', 'g');
                tmp = tmp.replace(re, map[j]);
            }

            let re = new RegExp('{_idx}', 'g');
            tmp = tmp.replace(re, parseInt(i)+1);

            out += tmp;
        }

        return out;
    };

    /**
     * @param node HTML DOM节点, 注意不是string
     * @param arr json数组 注意是数组类型
     * @return string 返回HTML字符串, 注意不是DOM节点
     */
    this.repeatNode = function (node, arr) {
        let out = [];
        for (let i=0; i<arr.length; i++) {
            let tmp = node.outerHTML;
            tmp = tmp.replace(/\s/g, ' '); //去掉回车换行, 减少空白符

            let map = arr[i];

            //先渲染内层的数组
            for (let j in map) {
                if (map[j] instanceof Array) { //数组, 递归替换
                    let subNode = node.querySelector('.'+j);
                    if (subNode) {
                        let subHtml = this.repeatNode(subNode, map[j]); //递归
                        let subTpl = subNode.outerHTML.replace(/\s/g, ' ');
                        tmp = tmp.replace(subTpl, subHtml);
                    }
                }
            }

            //再渲染内层的对象
            for (let j in map) {
                if (map[j] instanceof Object && !(map[j] instanceof Array)) { //对象, 递归替换
                    let subNode = node.querySelector('.'+j);
                    if (subNode) {
                        let subHtml = this.repeatNode(subNode, [map[j]]); //递归
                        let subTpl = subNode.outerHTML.replace(/\s/g, ' ')
                        tmp = tmp.replace(subTpl, subHtml);
                    }
                }
            }

            //最后渲染外层的键值对/字符串
            for (let j in map) {
                if (typeof map[j] === 'string' || typeof map[j] === 'number') { //字符串, 直接替换
                    let re = new RegExp('{' + j + '}', 'g');
                    tmp = tmp.replace(re, map[j]);
                }
            }

            out.push(tmp);
        }

        return out.join('');
    }

    //替换dom节点，id: 被替换的dom的id，str: 替换后的内容
    this.replaceDom = function (id, str){
        let dom = document.getElementById(id);
        if (dom) {
            dom.outerHTML = str;
        }
    }

    //获取dom节点的innerHTML
    this.getInnerHtmlById = function (id) {
        return document.getElementById(id).innerHTML;
    }

    this.htmlToNode = function (html) {
        let div = document.createElement('div');
        div.innerHTML = html;
        return div.firstElementChild;
    }

    this.isArray = function (o){
        return Object.prototype.toString.call(o) === '[object Array]';
    }

    //根据标签id更新内容
    this.changeContentById = function(srcId, targetId) {
        let src = document.getElementById(srcId);
        let target = document.getElementById(targetId);
        if (src && target) {
            target.innerHTML = src.innerHTML;
        } else {
            console.log('源id: '+srcId + ' 或 目标id: ' + targetId + ' 未找到!');
        }
    }

    //获取用户输入的内容
    this.getInputs = function (id, tagName) {
        let data = {};
        let arrTagName = tagName.split(',');
        for (let j=0; j<arrTagName.length; j++) {
            let tname = arrTagName[j];
            let inputs = document.getElementById(id).getElementsByTagName(tname);
            for (let i=0; i<inputs.length; i++) {
                let k = inputs[i].name;
                let v = inputs[i].value;

                let type = inputs[i].type;
                if (type === 'checkbox') {
                    if (inputs[i].checked === true) {
                        v = 1;
                    } else {
                        v = 0;
                    }
                }

                if (type === 'radio') {
                    if(inputs[i].checked === true){
                        v = inputs[i].value
                    }
                }

                data[k] = v;
            }
        }

        console.log(data);
        return data;
    }

    this.getYear = function () {
        let myDate = new Date();
        return myDate.getFullYear();
    }

    this.getMonth = function () {
        let myDate = new Date();
        return myDate.getMonth() + 1;
    }

    this.getDay = function () {
        let myDate = new Date();
        return myDate.getDate();
    }

    this.changeInnerHtml = function(id, str) {
        document.getElementById(id).innerHTML = str;
    }

    this.activeBorderBottom = function(id, color='#7E57C2') {
        if (document.getElementById(id) !== null) {
            let brothers = document.getElementById(id).parentNode.children;
            for (let i=0; i<brothers.length; i++) {
                brothers[i].style.borderBottom = '';
            }

            document.getElementById(id).style.borderBottom = '2px solid '+color;
        }
    }

    this.loading = function(id, txt='请稍后, 加载中...') {
        document.getElementById(id).innerHTML = '<div style="padding: 20px; text-align: center">'+txt+'</div>'
    }

    this.arraySearch = function (arr, key, val) {
        for (let i=0; i<arr.length; i++) {
            if (arr[i][key] !== 'undefined' && arr[i][key] === val) {
                return arr[i];
            }
        }
        return false;
    }

}